package com.alisiwei.core.base;

import java.util.List;
import javax.annotation.Resource;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Repository;


/**
 * @类名 BaseDao
 * @描述 hibernate通用dao实现 封装了大部分的dao操作
 */
@Repository
public class BaseDao<T> implements IBaseDao<T> {
	
	/**
	 * 自动注入sessionFactory
	 */
	@Resource 
	private SessionFactory sessionFactory;
	// logger日志对象
	protected Logger log = Logger.getLogger(this.getClass());

	/**
	 * @方法名 getCurrentSession 
	 * @描述 获得currentSession
	 * @return Session
	 */
	private Session getCurrentSession() {
		return sessionFactory == null ? null : sessionFactory.getCurrentSession() ;
	}
	
	/** 
	 * 描述：开启session
	 * 作者：zhangkai
	 * @return
	 */
    public Session getSession() {  
        //如果SessionFacroty不为空，则开启Session  
    	return (sessionFactory != null) ? sessionFactory.openSession() : null;  
    } 

	@Override
	public void save(T t) {
		getCurrentSession().save(t) ;
	}
	
	@Override
	public void saveList(List<T> list) {
		Session session = null;  
        if (list != null && list.size() > 0) {  
            try {  
                session = getSession(); // 获取Session  
                session.beginTransaction(); // 开启事物  
                T t = null; // 创建对象  
                // 循环获取对象  
                for (int i = 0; i < list.size(); i++) {  
                    t = (T) list.get(i); // 获取对象  
                    session.save(t); // 保存对象  
                    // 批插入的对象立即写入数据库并释放内存  
                    if (i % 100 == 0) {  
                        session.flush();  
                        session.clear();  
                    }  
                }  
                session.getTransaction().commit(); // 提交事物  
            } catch (Exception e) {  
                e.printStackTrace(); // 打印错误信息  
                session.getTransaction().rollback(); // 出错将回滚事物  
            } finally {  
            	if (session != null) {  
                    if (session.isOpen()) {  
                        session.close(); // 关闭Session  
                    }  
                }   
            }  
        }  
    } 

	@Override
	public void delete(T t) {
		getCurrentSession().delete(t) ;
		
	}

	@Override
	public void update(T t) {
		getCurrentSession().update(t) ;
		
	}

	@Override
    @SuppressWarnings("unchecked")  
    public T queryForObject(String hql, Object[] params) {  
        Query query = sessionFactory.getCurrentSession().createQuery(hql);  
        setQueryParams(query, params);  
        return (T) query.uniqueResult();  
    }  
   
    @Override
    @SuppressWarnings("unchecked")  
    public T queryForTopObject(String hql, Object[] params) {  
        Query query = sessionFactory.getCurrentSession().createQuery(hql);  
        setQueryParams(query, params);  
        return (T) query.setFirstResult(0).setMaxResults(1).uniqueResult();  
    }  
  
    @Override
    @SuppressWarnings("unchecked")  
    public List<T> queryForList(String hql, Object[] params) {  
        Query query = sessionFactory.getCurrentSession().createQuery(hql);  
        setQueryParams(query, params);  
        return query.list();  
    }  
  
    @Override
    @SuppressWarnings("unchecked")  
    public List<T> queryForList(final String hql, final Object[] params, final int recordNum) {  
        Query query = sessionFactory.getCurrentSession().createQuery(hql);  
        setQueryParams(query, params);  
        return query.setFirstResult(0).setMaxResults(recordNum).list();  
    }  
  
	  
	@Override
	public void deleteAll() {
		// TODO Auto-generated method stub
	}
	
	@Override
	public QueryResult hqlQueryPage(final String hql,final Pagination pagination, final List<String> values) {
		String queryHql = hql;
		if (values != null && values.size()>0) {
			queryHql += " order by ";
			for (int i = 0; i < values.size(); i++) {
				if (i == (values.size()-1)) {
					queryHql += values.get(i);
				} else {
					queryHql += values.get(i) + ",";
				}
			}
		}
		
		Query query = getCurrentSession().createQuery(queryHql).setFirstResult(pagination.getStartIndex()).setMaxResults(pagination.getPageSize());

		QueryResult queryResult = new QueryResult() ;
		queryResult.setRows(query.list());
		String countHql = "select count(*) "+hql;//封装查询总记录条数
		int allCount = getAllCount(countHql);//总记录条数
		queryResult.setTotal(allCount);
		return queryResult;
	}
	
	@Override
	public QueryResult sqlQueryPage(final String sql,final Pagination pagination, final List<String> values) {
		String queryHql = sql;
		if (values != null && values.size()>0) {
			queryHql += " order by ";
			for (int i = 0; i < values.size(); i++) {
				if (i == (values.size()-1)) {
					queryHql += values.get(i);
				} else {
					queryHql += values.get(i) + ",";
				}
			}
		}
		
		Query query = getCurrentSession().createSQLQuery(queryHql);
//		query.setResultTransformer(Transformers.aliasToBean(Bill.class));
		query = query.setFirstResult(pagination.getStartIndex()).setMaxResults(pagination.getPageSize());
		QueryResult queryResult = new QueryResult() ;
		queryResult.setRows(query.list());
		String countHql = "select count(*) from ("+sql+") a";//封装查询总记录条数
		long allCounts = countSQL(countHql);//总记录条数
		int allCount =  (int) allCounts;
		queryResult.setTotal(allCount);
		return queryResult;
	}

	@Override
	public int getAllCount(final String hql) {
		Query query = getCurrentSession().createQuery(hql);
		return Integer.parseInt(query.uniqueResult().toString());
	}
	
	@SuppressWarnings("rawtypes")
	public List findBySQL(String sql) {
		return this.getCurrentSession().createSQLQuery(sql).list();
	}

	@SuppressWarnings("unchecked")
	public List<T> findMapBySQL(String sql) {
		return this.getCurrentSession().createSQLQuery(sql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
	}

	@SuppressWarnings("rawtypes")
	public List findBySQL(String sql, ResultTransformer criteria) {
		return this.getCurrentSession().createSQLQuery(sql)
				.setResultTransformer(criteria).list();
	}
	

	private void setQueryParams(Query query, Object[] params) {  
		if (null == params) {  
			return;  
		}  
		for (int i = 0; i < params.length; i++) {  
			query.setParameter(i, params[i]);  
		}  
	}

	@Override
	public Long countSQL(String sql) {
		Object obj = this.getCurrentSession().createSQLQuery(sql).uniqueResult();
		Long retValue = null;
		if(null != obj){
			if(obj instanceof Double){
				retValue = ((Double) obj).longValue();
			}else{
				retValue = Long.valueOf(obj.toString());
			}
		}
		return retValue;
	}
}
